package cn.com.zsw.gblog.config.security;

import cn.com.zsw.gblog.config.cache.RedisCache;
import cn.com.zsw.gblog.constants.SysConstants;
import cn.com.zsw.gblog.modules.user.entity.GbUserEntity;
import cn.com.zsw.gblog.modules.user.service.GbUserService;
import cn.com.zsw.gblog.utils.JwtUtils;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author: shiwangZhou
 * @description: 是的
 * @date: 2020-09-09 15:45
 */
@Slf4j
@Component
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {

    @Autowired
    RedisCache redisCache;
    @Autowired
    GbUserService userService;

    /**
     * Creates an instance which will authenticate against the supplied
     * {@code AuthenticationManager} and which will ignore failed authentication attempts,
     * allowing the request to proceed down the filter chain.
     *
     * @param authenticationManager the bean to submit authentication requests to
     */
    public JwtAuthorizationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String token = request.getHeader(JwtUtils.TOKEN_HEADER);
        if (StringUtils.isEmpty(token)) {
            chain.doFilter(request, response);
            return;
        }
        String tokenCache = redisCache.getCacheObject(SysConstants.REDIS_JWT_TOKEN_ID + token);
        if (!StringUtils.isEmpty(tokenCache)) {
            UsernamePasswordAuthenticationToken authentication = getAuthentication(token);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        chain.doFilter(request, response);


    }

    private UsernamePasswordAuthenticationToken getAuthentication(String header) {
//        用户名
        String userId;
//        权限
        Set<GrantedAuthority> authorities = new HashSet<>();
//            解析token
        Claims claims = JwtUtils.getTokenBody(header);
        logger.info("claims：" + claims);
//            获取用户名
        userId = claims.getSubject();
//            获取权限
        List<String> list = JSON.parseArray(claims.get(SysConstants.JWT_PERMISSIONS_KEY).toString(), String.class);
        if (!org.springframework.util.StringUtils.isEmpty(list)) {
            for (String authority : list) {
                authorities.add(new SimpleGrantedAuthority(authority));
            }
        }
        GbUserEntity gbUser = userService.getById(userId);
//            踩坑提醒 此处password不能为null
        User principal = new User(gbUser.getUsername(), "", authorities);
        return new UsernamePasswordAuthenticationToken(principal, null, authorities);

    }
}